import logging
from django.conf import settings

# The main entry point:
def invokeConnieProcess(input):
    """Figures out which harness to use and invokes connie with it,
    using the argument as input.  Argument may be a string, or a list
    of strings (for input chaining)"""
    harnessName = settings.CONNIE_HARNESS
    logging.debug('Will attempt to invoke connie using harness ' + harnessName)
    harness = get_class(harnessName)
    return harness(input)

def invokeBySubprocess(input):
    """
    Invoke the connie process, and return the results.  Input is
    expected to be either a string of the formatted input or a list of
    formatted strings with place-holders for the next-file name in all
    but the last, and the output will be the output as generated by
    connie.  Currently "invoke" means writing the input data to a tmp
    file and invoking the process with that; results are read from the
    process' stdout.  Future versions may be regular stdin->stdout
    filter invocation.
    """
    import os, subprocess, tempfile

    if isinstance(input, (str, unicode)):
        input = [input]

    # Work backwards through the list; the last file will never have a
    # "next" file by definition, so each file we create can then be
    # used to specify the follow-on of the previous file.
    paths = []
    for inputStr in reversed(input):
        if paths:
            inputStr = inputStr % paths[-1]
        with tempfile.NamedTemporaryFile(prefix='connieinp', delete=False) as outfile:
            paths.append(outfile.name)
            outfile.write(inputStr)

    # execute connie, and wait for the results from its stdout (main
    # file in the series will be the last in the list):
    connie = subprocess.Popen([settings.CONNIE_EXECUTABLE, paths[-1]],
                              stdout=subprocess.PIPE,
                              env=settings.CONNIE_ENV)
    (retdata, _err) = connie.communicate()

    # clean up before returning:
    for path in paths: os.remove(path)
    return retdata

def dummyInvocation(inputStr):
    """Just for testing; simply returns the contents of a file (so
    won't line up or anything).  File can be specified as DUMMY_OUTPUT
    in the settings, or a default will be used."""
    dummyFile = getattr(settings, 'DUMMY_OUTPUT', '/home/hep016/Projects/connie/test-data/output_14.txt')
    with open(dummyFile, 'r') as f:
        return f.read()

# These two utilities are taken mostly as-is from django-compress:
def get_class(class_string):
    "Convert a string version of a function name to the callable object."

    if not hasattr(class_string, '__bases__'):
        try:
            class_string = class_string.encode('ascii')
            mod_name, class_name = get_mod_func(class_string)
            if class_name != '':
                class_string = getattr(__import__(mod_name, {}, {}, ['']), class_name)
        except (ImportError, AttributeError):
            raise Exception('Failed to import filter %s' % class_string)

    return class_string

def get_mod_func(callback):
    """
    Converts 'django.views.news.stories.story_detail' to
    ('django.views.news.stories', 'story_detail')
    """
    try:
        dot = callback.rindex('.')
    except ValueError:
        return callback, ''
    return callback[:dot], callback[dot+1:]
